package com.ikingtech.platform.service.system.role.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ikingtech.framework.sdk.base.model.PageResult;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.role.model.RoleDTO;
import com.ikingtech.framework.sdk.role.model.RoleQueryParamDTO;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.platform.service.system.role.entity.RoleDO;
import com.ikingtech.platform.service.system.role.entity.RoleDataScopeDO;
import com.ikingtech.platform.service.system.role.mapper.RoleMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author tie yan
 */
@Slf4j
@Service
@AllArgsConstructor
public class RoleRepository extends ServiceImpl<RoleMapper, RoleDO> {

    private final RoleDataScopeRepository dataScopeService;

    public List<RoleDTO> modelConvert(List<RoleDO> entities) {
        Map<String, List<String>> dataScopeMap = Tools.Coll.convertGroup(this.dataScopeService.listByRoleIds(Tools.Coll.convertList(entities, RoleDO::getId)), RoleDataScopeDO::getRoleId, RoleDataScopeDO::getDataScopeCode);
        return Tools.Coll.convertList(entities, entity -> this.modelConvert(entity, dataScopeMap.get(entity.getId())));
    }

    public RoleDTO modelConvert(RoleDO entity, List<String> dataScopeCodes) {
        RoleDTO role = Tools.Bean.copy(entity, RoleDTO.class);
        role.setDataScopeCodes(dataScopeCodes);
        if (null != role.getDataScopeType()) {
            role.setDataScopeTypeName(role.getDataScopeType().description);
        }
        return role;
    }

    public PageResult<RoleDO> listPage(RoleQueryParamDTO queryParam, String tenantCode) {
        return PageResult.build(this.page(new Page<>(queryParam.getPage(), queryParam.getRows()), Wrappers.<RoleDO>lambdaQuery()
                .like(Tools.Str.isNotBlank(queryParam.getName()), RoleDO::getName, queryParam.getName())
                .eq(Tools.Str.isNotBlank(queryParam.getDataScopeType()), RoleDO::getDataScopeType, queryParam.getDataScopeType())
                .like(Tools.Str.isNotBlank(queryParam.getRemark()), RoleDO::getRemark, queryParam.getRemark())
                .eq(RoleDO::getTenantCode, tenantCode)
                .orderByDesc(RoleDO::getCreateTime)));
    }

    public List<RoleDO> listByTenantCode(String tenantCode) {
        return this.list(Wrappers.<RoleDO>lambdaQuery()
                .eq(RoleDO::getTenantCode, tenantCode));
    }

    public List<RoleDO> listByDomainCodeAndTenantCodeAndAppCode(String domainCode, String tenantCode, String appCode) {
        return this.list(Wrappers.<RoleDO>lambdaQuery()
                .eq(Tools.Str.isNotBlank(domainCode), RoleDO::getDomainCode, domainCode)
                .eq(Tools.Str.isNotBlank(tenantCode), RoleDO::getTenantCode, tenantCode)
                .eq(Tools.Str.isNotBlank(appCode), RoleDO::getAppCode, appCode));
    }

    public List<RoleDO> between(Object startValue, Object endValue) {
        return this.list(Wrappers.<RoleDO>query().lambda()
                .between(RoleDO::getSortOrder, startValue, endValue)
                .eq(RoleDO::getTenantCode, Me.tenantCode()));
    }

    public Integer getMaxSortOrder() {
        List<Number> orders = this.listObjs(Wrappers.<RoleDO>query().lambda()
                .select(RoleDO::getSortOrder)
                .eq(RoleDO::getTenantCode, Me.tenantCode())
                .orderByDesc(RoleDO::getSortOrder), Number.class::cast);
        return Tools.Coll.isBlank(orders) ? 0 : orders.get(0).intValue();
    }

    public Boolean exist(String id) {
        return this.baseMapper.exists(Wrappers.<RoleDO>lambdaQuery().eq(RoleDO::getId, id));
    }

    public void removeByTenantCode(String tenantCode) {
        this.remove(Wrappers.<RoleDO>query().lambda().eq(RoleDO::getTenantCode, tenantCode));
    }

    public List<RoleDO> listByName(String name, String domainCode, String tenantCode, String appCode) {
        return this.list(Wrappers.<RoleDO>lambdaQuery()
                .like(RoleDO::getName, name)
                .eq(Tools.Str.isNotBlank(domainCode), RoleDO::getDomainCode, domainCode)
                .eq(Tools.Str.isNotBlank(tenantCode), RoleDO::getTenantCode, tenantCode)
                .eq(Tools.Str.isNotBlank(appCode), RoleDO::getAppCode, appCode));
    }
}
